#include <i386/page.h>

/*
 * page_map_static_mem - 映射内核静态内存区域
 * @start: 开始物理地址
 * @end: 结束物理地址
 * 
 * 把物理和内核虚拟地址进行映射
 */
void page_map_static_mem(unsigned int start, unsigned int end)
{
	/* ----映射静态内存---- */
	//把页目录表设置
	pde_t *pdt = (pde_t *)PAGE_DIR_VIR_ADDR;

	// 求出目录项数量
	unsigned int pde_nr = (end - start) / (1024 * PAGE_SIZE);
    
	// 先获取的页数
	unsigned int pte_nr = (end-start)/PAGE_SIZE;

	// 获取页数中余下的数量，就是页表项剩余数
	pte_nr = pte_nr % 1024;
	
	//跳过页表区域中已经映射的页表
	pte_t *pte_addr = (pte_t *) (PAGE_TABLE_PHY_ADDR + 
			PAGE_SIZE * PAGE_TABLE_PHY_NR);

	int i, j;
	// 根据页目录项来填写
	for (i = 0; i < pde_nr; i++) {
		//填写页目录表项
		//把页表地址和属性放进去
		pdt[512 + PAGE_TABLE_PHY_NR + i] = (unsigned int)pte_addr | (PG_P_1 | PG_RW_W | PG_US_S);
		
		for (j = 0; j < PAGE_ENTRY_NR; j++) {
			//填写页页表项

			//把物理地址和属性放进去
			pte_addr[j] = start | (PG_P_1 | PG_RW_W | PG_US_S);
			//指向下一个物理页
			start += PAGE_SIZE;
		}
		//指向下一个页表
		pte_addr += PAGE_SIZE;
	}
	// 根据剩余的页表项填写

	//有剩余的我们才填写
	if (pte_nr > 0) {
		// i 和 pte_addr 的值在上面的循环中已经设置
		pdt[512 + PAGE_TABLE_PHY_NR + i] = (unsigned int)pte_addr | (PG_P_1 | PG_RW_W | PG_US_S);
		
		// 填写剩余的页表项数量
		for (j = 0; j < pte_nr; j++) {
			//填写页页表项
			//把物理地址和属性放进去
			pte_addr[j] = start | (PG_P_1 | PG_RW_W | PG_US_S);
			
			//指向下一个物理页
			start += PAGE_SIZE;
		}
	}

	/* 在开启分页模式之后，我们的内核就运行在高端内存，
	那么，现在我们不能通过低端内存访问内核，所以，我们在loader
	中初始化的0~8MB低端内存的映射要取消掉才行。
	我们把用户内存空间的页目录项都清空 */ 
	
	for (i = 0; i < 512; i++) {
		pdt[i] = 0;
	}
}
